#include"include/playlistwidget.h"
#include<taglib/fileref.h>
#include<taglib/tag.h>
#include<stdlib.h>
#include<time.h>
#include"include/trackplayer.h"
#include"include/trackinfowidget.h"
#include"include/lyrictool.h"
#include"ui_playlistwidget.h"
PlayListWidget::PlayListWidget(QWidget *parent):QWidget(parent),ui(new Ui::PlayListWidget)
{
    ui->setupUi(this);
    setFixedSize(300,310);
    ui->treeWgt->setContextMenuPolicy(Qt::CustomContextMenu);       //custom context menu
    setWindowFlags(Qt::Tool);
    setWindowTitle(QObject::tr("Playlist"));
    player=0;
    trackInfoWidget=0;
    playMode=ORDINALPLAY;
    creatActions();
    creatConnections();
    readPlayList();

    qsrand((unsigned int)time(NULL));
}

void PlayListWidget::creatActions()
{
    addTrackAct=new QAction(QObject::tr("Add &Music"),this);
    addTrackAct->setShortcut(QKeySequence(Qt::ALT+Qt::Key_A));
    addTrackAct->setShortcutContext(Qt::ApplicationShortcut);
    addDirectoryAct=new QAction(QObject::tr("Add &Directory"),this);
    addDirectoryAct->setShortcut(QKeySequence(Qt::ALT+Qt::Key_F));
    addDirectoryAct->setShortcutContext(Qt::ApplicationShortcut);
    addBtnMenu=new QMenu(this);
    addBtnMenu->addAction(addTrackAct);
    addBtnMenu->addAction(addDirectoryAct);
    ui->addBtn->setMenu(addBtnMenu);
    ui->addBtn->setPopupMode(QToolButton::InstantPopup);

    viewTrackInfoAct=new QAction(QObject::tr("&View Track Information"),this);
    delCurrentTrackAct=new QAction(QObject::tr("&Delete Current Track"),this);
    clearPlayListAct=new QAction(QObject::tr("&Clear Playlist"),this);
    trackMenu=new QMenu(this);
    trackMenu->addAction(viewTrackInfoAct);
    trackMenu->addAction(delCurrentTrackAct);

    trackMenu->addAction(clearPlayListAct);
    delMenu=new QMenu(this);
    delMenu->addAction(delCurrentTrackAct);
    delMenu->addAction(clearPlayListAct);
    ui->delBtn->setMenu(delMenu);
    ui->delBtn->setPopupMode(QToolButton::InstantPopup);

    sortByAlbumAct=new QAction(QObject::tr("Sort Tracks By Album"),this);
    sortByArtistAct=new QAction(QObject::tr("Sort Tracks By Artist"),this);
    sortByFileNameAct=new QAction(QObject::tr("Sort Tracks By File Name"),this);
    sortByTitleAct=new QAction(QObject::tr("Sort Tracks By Title"),this);
    sortMenu=new QMenu(this);
    sortMenu->addAction(sortByTitleAct);
    sortMenu->addAction(sortByArtistAct);
    sortMenu->addAction(sortByAlbumAct);
    sortMenu->addAction(sortByFileNameAct);
    ui->sortBtn->setMenu(sortMenu);
    ui->sortBtn->setPopupMode(QToolButton::InstantPopup);
}

void PlayListWidget::creatConnections()
{
    connect(ui->treeWgt,SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),this,SLOT(onItemDbleClicked(QTreeWidgetItem*,int)));
    connect(addTrackAct,SIGNAL(triggered()),this,SLOT(onAddTrackTriggered()));
    connect(addDirectoryAct,SIGNAL(triggered()),this,SLOT(onAddDirTriggered()));

    connect(viewTrackInfoAct,SIGNAL(triggered()),this,SLOT(onViewTrackInfoTriggered()));
    connect(delCurrentTrackAct,SIGNAL(triggered()),this,SLOT(onDelCurrentTrackTriggered()));
    connect(clearPlayListAct,SIGNAL(triggered()),this,SLOT(onClearPlayListTriggered()));
    connect(ui->treeWgt,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(onContextMenuRequest(QPoint)));
    connect(sortByFileNameAct,SIGNAL(triggered()),this,SLOT(onSortByFileNameTriggered()));
    connect(sortByTitleAct,SIGNAL(triggered()),this,SLOT(onSortByTitleTriggered()));
    connect(sortByArtistAct,SIGNAL(triggered()),this,SLOT(onSortByArtistTriggered()));
    connect(sortByAlbumAct,SIGNAL(triggered()),this,SLOT(onSortByAlbumTriggered()));
}

void PlayListWidget::addTrack(const QString& dirName,const QStringList &fileNames,bool save)
{
    //called by triggerring add tracks action
    QTreeWidget *tree=ui->treeWgt;
    QString fileName;
    QTreeWidgetItem *item;
    foreach(fileName,fileNames)
    {
        QStringList slist(fileName);
        item=new QTreeWidgetItem(slist);
        tree->addTopLevelItem(item);
        QString file(dirName);
        file.append("/");
        file.append(fileName);
        queue.insertMulti(fileName,file);
        trackFiles.append(file);
    }
    if(save)
        savePLayList();
}

void PlayListWidget::addTrack(const QStringList &tracks, const QStringList &path, bool save)
{
    //called by triggerring sort tracks action or reading playlist from config file
    QTreeWidget *tree=ui->treeWgt;
    QString fileName;
    QTreeWidgetItem *item;
    int count=tracks.size();
    for(int i=0;i<count;++i)
    {
        QStringList slist(tracks.at(i));
        item=new QTreeWidgetItem(slist);
        tree->addTopLevelItem(item);
        queue.insertMulti(tracks.at(i),path.at(i));
    }
    if(save)
        savePLayList();
}

void PlayListWidget::onItemDbleClicked(QTreeWidgetItem *item, int column)
{
    ui->treeWgt->setCurrentItem(item);
    QString file=queue[item->text(0)];
    if(player)
        player->playTrack(file);
}

void PlayListWidget::playNextTrack()
{
    QTreeWidget *tree=ui->treeWgt;
    QTreeWidgetItem *item=0;
    switch(playMode)
    {
    case TRACKREPEAT:
        item=tree->currentItem();
        break;
    case LISTREPEAT:
        item=tree->itemBelow(tree->currentItem());
        if(item)
            tree->setCurrentItem(item);
        else
        {
            item=tree->topLevelItem(0);
            if(item)
                tree->setCurrentItem(item);
        }
        break;
    case RANDOMPLAY:
    {
        int idx=qrand()%(tree->topLevelItemCount()+1);
        item=tree->topLevelItem(idx);
        tree->setCurrentItem(item);
    }
        break;
    default:
        item=tree->itemBelow(tree->currentItem());
        if(item)
            tree->setCurrentItem(item);
        break;
    }
    if(item)
    {
        QString file=queue.value(item->text(0));
        if(player)
            player->playTrack(file);
    }
}

void PlayListWidget::playPrevTrack()
{
    QTreeWidget *tree=ui->treeWgt;
    QTreeWidgetItem* item=0;

    switch(playMode)
    {
    case TRACKREPEAT:
        item=tree->currentItem();
        break;
    case LISTREPEAT:
        item=tree->itemAbove(tree->currentItem());
        if(item)
            tree->setCurrentItem(item);
        else
        {
            item=tree->topLevelItem(tree->topLevelItemCount()-1);
            if(item)
                tree->setCurrentItem(item);
        }
        break;
    case RANDOMPLAY:
    {
        int idx=qrand()%(tree->topLevelItemCount()+1);
        item=tree->topLevelItem(idx);
        tree->setCurrentItem(item);
    }
        break;
    default:
        item=tree->itemAbove(tree->currentItem());
        if(item)
        {
            tree->setCurrentItem(item);
        }
        break;
    }
    if(item)
    {
        QString file=queue.value(item->text(0));
        if(player)
            player->playTrack(file);
    }
}

void PlayListWidget::playCurrentTrack()
{
    QTreeWidget *tree=ui->treeWgt;
    QTreeWidgetItem *item=0;
    item=tree->currentItem();
    if(item)
    {
        QString file=queue.value(item->text(0));
        if(player)
            player->playTrack(file);
    }
}

void PlayListWidget::playOrPause(bool b)
{
    QString tkName=player->currentTackName();
    if(tkName.isEmpty())
        playCurrentTrack();
    else if(player)
    {
        if(b)
            player->playOrPause(true);
        else if(player->state()!=Phonon::StoppedState)
            player->playOrPause(false);
    }
}

void PlayListWidget::stop()
{
    if(player)
        player->stop();
}

void PlayListWidget::onAboutToFinished()
{
    QTreeWidget *tree=ui->treeWgt;
    QTreeWidgetItem* item=0;
    item=tree->itemBelow(tree->currentItem());
    if(item)
    {
        tree->setCurrentItem(item);
        QString file=queue[item->text(0)];
        if(player)
            player->enqueue(file);
    }
}

void PlayListWidget::onAddTrackTriggered()
{
    QString fileName = QFileDialog::getOpenFileName(this, tr("Add Music"),
                                                    QDesktopServices::storageLocation(
                                                        QDesktopServices::MusicLocation),
                                                    tr("Audio (*.mp3 *.aac *.ogg *.wav *.wma)"));
    if(!fileName.isEmpty())
    {
        QFileInfo file(fileName);
        addTrack(file.absolutePath(),QStringList(file.fileName()),true);
    }
}

void PlayListWidget::onAddDirTriggered()
{
    QString dirName=QFileDialog::getExistingDirectory(this, tr("Open Directory"),
                                                      QDesktopServices::storageLocation(
                                                          QDesktopServices::MusicLocation),
                                                      QFileDialog::ShowDirsOnly
                                                      | QFileDialog::DontResolveSymlinks);
    if(!dirName.isEmpty())
    {
        QDir dir(dirName);
        QStringList filters;
        filters<<"*.mp3"<<"*.ogg"<<"*.wav"<<"*.wma"<<"*.aac";
        addTrack(dirName,dir.entryList(filters),true);
    }
}

void PlayListWidget::setPlayer(TrackPlayer *p)
{
    player=p;
}

void PlayListWidget::closeEvent(QCloseEvent *ce)
{
    emit closeRequest();
    ce->setAccepted(false);
}

void PlayListWidget::readPlayList()
{
    QSettings sts("HJF","Minip");
    QStringList titles=sts.value("MinipPlayListTitle").toStringList();
    QStringList tracks=sts.value("MinipPlayListTrack").toStringList();
    trackFiles<<tracks;
    addTrack(titles,tracks,false);
}

void PlayListWidget::savePLayList()
{
    QSettings sts("HJF","Minip");
    QStringList titles(queue.keys());
    QStringList tracks(queue.values());
    sts.setValue("MinipPlayListTitle",titles);
    sts.setValue("MinipPlayListTrack",tracks);
    sts.sync();
}

void PlayListWidget::onContextMenuRequest(const QPoint &pos)
{
    trackMenu->exec(ui->treeWgt->mapToGlobal(pos));
}

void PlayListWidget::onViewTrackInfoTriggered()
{
    QTreeWidgetItem *item=0;
    item=ui->treeWgt->currentItem();
    if(item)
    {
        if(trackInfoWidget)
        {
            delete trackInfoWidget;
            trackInfoWidget=0;
        }
        QString fileName=queue.value(item->text(0));
        trackInfoWidget=new TrackInfoWidget(fileName);
        trackInfoWidget->show();
    }
}

void PlayListWidget::onDelCurrentTrackTriggered()
{
    QTreeWidgetItem *item=0;
    item=ui->treeWgt->currentItem();
    if(item)
    {
        QString file=item->text(0);
        int index=ui->treeWgt->indexOfTopLevelItem(item);
        ui->treeWgt->takeTopLevelItem(index);
        delete item;
        item=0;
        trackFiles.removeOne(queue.value(file));
        QString f=queue.take(file);
        if(player)
        {
            if(f==player->currentTackName())
                stop();
        }
        savePLayList();
    }
}

void PlayListWidget::onClearPlayListTriggered()
{
    ui->treeWgt->clear();
    queue.clear();
    trackFiles.clear();
    stop();
    savePLayList();
}

void PlayListWidget::onSortByFileNameTriggered()
{
    QStringList files;
    QString name;
    foreach(name,trackFiles)
    {
        QFileInfo f(name);
        files<<f.fileName();
    }
    ui->treeWgt->clear();
    queue.clear();
    stop();
    addTrack(files,trackFiles,true);
}

void PlayListWidget::onSortByTitleTriggered()
{
    QMap<QString,QString> trackMap;
    QMap<QString,QString> otherTrackMap;
    QString name;
    foreach(name,trackFiles)
    {
        QString _title(LyricTool::trackTitle(name).trimmed());
        if(!_title.isEmpty())
        {
            trackMap.insertMulti(_title,name);
        }
        else
        {
            QFileInfo f(name);
            otherTrackMap.insertMulti(f.fileName(),name);
        }
    }
    ui->treeWgt->clear();
    queue.clear();
    stop();
    //the QMap can sort keys and values in ascending order
    addTrack(QStringList(trackMap.keys()),QStringList(trackMap.values()),false);
    addTrack(QStringList(otherTrackMap.keys()),QStringList(otherTrackMap.values()),true);
}

void PlayListWidget::onSortByAlbumTriggered()
{
    QMap<QString,QString> trackMap;
    QMap<QString,QString> otherTrackMap;
    QString name;
    foreach(name,trackFiles)
    {
        QString _album=LyricTool::trackAlbum(name).trimmed();
        QString _title=LyricTool::trackTitle(name).trimmed();
        if((!_album.isEmpty())&&(!_title.isEmpty()))
        {
            _album.append("-").append(_title);
            trackMap.insertMulti(_album,name);
        }
        else
        {
            QFileInfo f(name);
            otherTrackMap.insertMulti(f.fileName(),name);
        }
    }
    ui->treeWgt->clear();
    queue.clear();
    stop();
    //the QMap can sort keys and values in ascending order
    addTrack(QStringList(trackMap.keys()),QStringList(trackMap.values()),false);
    addTrack(QStringList(otherTrackMap.keys()),QStringList(otherTrackMap.values()),true);
}

void PlayListWidget::onSortByArtistTriggered()
{
    QMap<QString,QString> trackMap;
    QMap<QString,QString> otherTrackMap;
    QString name;
    foreach(name,trackFiles)
    {
        QString _artist=LyricTool::trackArtist(name).trimmed();
        QString _title=LyricTool::trackTitle(name).trimmed();
        if((!_artist.isEmpty())&&(!_title.isEmpty()))
        {
            _artist.append("-").append(_title);
            trackMap.insertMulti(_artist,name);
        }
        else
        {
            QFileInfo f(name);
            otherTrackMap.insertMulti(f.fileName(),name);
        }
    }
    ui->treeWgt->clear();
    queue.clear();
    stop();
    //the QMap can sort keys and values in ascending order
    addTrack(QStringList(trackMap.keys()),QStringList(trackMap.values()),false);
    addTrack(QStringList(otherTrackMap.keys()),QStringList(otherTrackMap.values()),true);
}

void PlayListWidget::setPlayMode(PlayMode mode)
{
    playMode=mode;
}
